import codetree.CodeTree;
import generate.Generate;
import groum.model.db.Record;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.util.*;

import static org.apache.commons.lang.StringEscapeUtils.escapeJava;
import static org.apache.commons.lang.StringEscapeUtils.unescapeHtml;
import static org.apache.commons.lang.StringEscapeUtils.unescapeJava;

/**
 * The Servlet
 * Created by wangxin on 2017/4/20.
 */
@WebServlet(name = "CodeRecommendationServlet")
public class CodeRecommendationServlet extends HttpServlet {

    String[] strs; // generate statements
    private List<Generate> generateList = new ArrayList<>();
    private Map<String, Map<String, List>> parameterList = new HashMap<>();
    private List<List<String>> importInfoList = new ArrayList<>();

    public static Map<String,Record> map;
    public static Map<String,Boolean> castMap = new HashMap<>();
    public List<String> jdkList = new ArrayList<>();
    @Override
    public void init(){
        try {
            /*
            Runtime run = Runtime.getRuntime();
            String[] cmd = new String[] {"python", "/home/x/mydisk/Zhao.treelstm/lstmtree-class.py"};
            run.exec(cmd);
            */
//            System.out.println("start load groum map");
//            ObjectInputStream in = new ObjectInputStream(new FileInputStream("/home/x/mydisk/groumMapNew7_1.txt"));
//            Object object = null;
//            object = in.readObject();
//            map = (Map<String,Record>)object;
//            in.close();
//            System.out.println("finish load groum map");
//            System.out.println("start cast read");
//            File fileTypeCast = new File( "/home/x/IdeaProjects/CodeRecommendation/Extractor/src/main/java/codetree/configs/type_cast.config");
//            FileInputStream fileInputStream = new FileInputStream(fileTypeCast);
//            Scanner scanner = new Scanner(fileInputStream);
//            while (scanner.hasNextLine()) {
//                castMap.put(scanner.nextLine(), true);
//            }
//            scanner.close();
//            fileInputStream.close();
//            System.out.println("finish cast read");
//            System.out.println("start jdkList");
//            String globalPath = "/home/x/IdeaProjects/CodeRecommendation";
            String globalPath = "/mydisk/fudan_se_dl/code_recommendation";
            File fileClassNameMap = new File(globalPath + "/JDKCLASS.txt");
            FileInputStream fileInputStream2 = new FileInputStream(fileClassNameMap);
            Scanner scanner2 = new Scanner(fileInputStream2);
            while (scanner2.hasNextLine()) {
                String line = scanner2.nextLine();
                jdkList.add(line);
            }
            scanner2.close();
            fileInputStream2.close();
            System.out.println("finish jdkList");
        }catch(Exception e){

        }
    }
    // Session Pool
    private static Map<String, HttpSession> sessionPool = new HashMap<>();

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // Get session
        HttpSession session = request.getSession();
        String sessionID = session.getId();
        sessionPool.put(sessionID, session);
        //System.out.println("Session visit: " + sessionID);

        String callback  = request.getParameter("callback");
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        request.setCharacterEncoding("UTF-8");
        String operation = request.getParameter("operation");
        if(operation.equals("predict")) {
            String spacenum = request.getParameter("spacenum");
            String space = "";
            if(spacenum != null) {
                int spaceNum = Integer.parseInt(spacenum);
                for (int i = 0; i < spaceNum; i++) {
                    space += " ";
                }
            }
            String rawcode = unescapeHtml(request.getParameter("rawcode"));
            rawcode = rawcode.replaceAll("woshidanyinhaochenchi","'");
            rawcode = rawcode.replaceAll("dotchenchi",".");
            //System.out.println(rawcode);
            rawcode = rawcode.replaceAll("\t \" \t","\"" );

            //RawCodeHandler rawCodeHandler = new RawCodeHandler();
            RawCodeHandler rawCodeHandler = new RawCodeHandler(jdkList,space);
            List<String> completecode = rawCodeHandler.handleRawCode(rawcode);//handle rawcode
            generateList = rawCodeHandler.getGenerateList();
            importInfoList = rawCodeHandler.getImportInfoList();
            if(completecode == null){
                out.write(callback + "({})");
            }
            else if(completecode.size() == 0){
                out.write(callback + "({\"statements\":[]})");
            }
            else {
                strs = new String[completecode.size()];
                for (int i = 0; i < completecode.size(); i++) {
                    strs[i] = completecode.get(i).replace("\n", "<br> \\n");
                    //System.out.println(strs[i]);
                }

                //String[] strs = {"int i = 0;","File f = new File(\"\");","String s;"};
                StringBuilder statements = new StringBuilder("{\"statements\":[");
                for (String s : strs) {
                    statements.append("\'").append(s).append("\',");
                }
                statements = statements.replace(statements.lastIndexOf(","), statements.lastIndexOf(",") + 1, "]}");
                out.write(callback + "(" + statements.toString() + ")");
            }
        }
        else if(operation.equals("selectStatement")){
            String statement = request.getParameter("statement");
            String index = request.getParameter("index");

            //System.out.println(statement);
//            for (int i = 0; i < generateList.size(); i++) {
//                Set set = generateList.get(i).getParameterMap().keySet();
//                if(set.contains(statement) || set.contains(statement.substring(0, statement.lastIndexOf(";")))){// contain ; or not
//                    parameterList = generateList.get(i).getParameterMap();
//                }
//            }
//            // test
//            for (String key : parameterList.keySet()) {
//                System.out.println(key + ":" + parameterList.get(key));
//            }
            StringBuilder stringBuilder = new StringBuilder("\'");
            int i = Integer.parseInt(index);
            if(importInfoList.size() > 0 && i <= importInfoList.size()-1) {
                List<String> importInfo = importInfoList.get(i);
                if(importInfo.size()>0) {
                    for (int j = 0; j < importInfo.size() - 1; j++) {
                        stringBuilder.append(importInfo.get(j)).append("\',\'");
                    }
                    stringBuilder.append(importInfo.get(importInfo.size() - 1));
                }
            }
            stringBuilder.append("\'");
            String statements = "{\"statements\":[],\"importinfo\":[" + stringBuilder.toString() + "]}";
            out.write(callback + "(" + statements + ")");
        }
        else if(operation.equals("selectParameter")){
            System.out.println("select parameter....");
            String parameter = request.getParameter("parameter");
            String line = request.getParameter("line");
            String lineAfter = request.getParameter("lineAfter");
            String tokenBefore = request.getParameter("tokenBefore");

            /*System.out.println("Line:" + line);
            System.out.println("Line after:" + lineAfter);
            System.out.println("Token before:" + tokenBefore);*/
            // Update the parameter list of generate
            int i = -1;
            for (i = 0; i < strs.length; i++) {
                if(strs[i].equals(line)){
                    strs[i] = lineAfter;
                    break;
                }
            }
            System.err.println("i:" + i);
            if(!generateList.get(i).getParameterMap().keySet().contains(line)){
                line = line.substring(0,line.lastIndexOf(";"));
            }
            System.out.println("line now:" + line);
            try {
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
                objectOutputStream.writeObject(generateList.get(i).getParameterMap().get(line));
                ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
                ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
                Map<String, List> variables = (Map<String, List>)objectInputStream.readObject();
                // Update variables, exchange parameter
                List candidateVariables = variables.get(tokenBefore);
                candidateVariables.set(variables.get(tokenBefore).indexOf(parameter), tokenBefore);
                variables.put(parameter, candidateVariables);
                variables.remove(tokenBefore);
                generateList.get(i).getParameterMap().put(lineAfter, variables);
                parameterList = generateList.get(i).getParameterMap();
            } catch (ClassNotFoundException e) {
                //e.printStackTrace();
            }

            String statements = "{\"statements\":[]}";
            out.write(callback + "("+statements+")");


        }
        else if(operation.equals("getParameter")){
            String line = request.getParameter("line");
            String tokenBefore = request.getParameter("tokenBefore");
            System.err.println(line);
            System.err.println(tokenBefore);

         //   if(!parameterList.keySet().contains(line)){
         //       line = line.substring(0,line.lastIndexOf(";"));
         //   }
            Map<String, List> variables = parameterList.get(line);
            List<String> candidateVariables = variables.get(tokenBefore);

            //list
            StringBuilder parameters = new StringBuilder("{\"parameters\":[");
            for (String s: candidateVariables) {
                parameters.append("\'").append(s).append("\',");
            }
            parameters = parameters.replace(parameters.lastIndexOf(","), parameters.lastIndexOf(",") + 1, "]}" );
            out.write(callback + "("+parameters.toString()+")");
        }
        out.close();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request,response);
    }
}
